package cn.txauction.common.utils;

import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.BufferedOutputStream;
import java.io.OutputStream;
import java.util.List;

import org.jdom.*;
import org.jdom.input.SAXBuilder;
import org.jdom.xpath.XPath;


//一、将网页资料以excel报表以线上浏览方式呈现 
//<%@ page c %>
//
//线上浏览的方式： response.setHeader("Content-disposition","inline; filename=test1.xls"); 
//下载的方式： response.setHeader("Content-disposition","attachment; filename=test2.xls");
//<html>内容</html>

//二、输出到客户端
//response.reset();
//response.setContentType("application/vnd.ms-excel");
//ExcelCreator.writeExcel(response.getOutputStream(),ResultSet);
@SuppressWarnings("unchecked")
public class ExcelCreator {
	 // 写入Excel的Writer对象
    private String filePrefix = "";
    private BufferedOutputStream writer=  null;
	private Element configroot;
    private static String CONFIG_FILE_NAME =  "cn\\txauction\\common\\config\\csvConfig.xml";
    private boolean hasConfig = true;
    private String configNode = "";
    
//    //分隔符
    private char TAB = '\t';        
    private char COMMA = ',';
    

    public ExcelCreator(OutputStream writer){
    	this.writer = new BufferedOutputStream(writer);
    	initconfig();
    }
    private void initconfig() {
    	SAXBuilder sb = new SAXBuilder();
    	if(!CONFIG_FILE_NAME.trim().equals("")){
	    	try{
	    		Document doc = sb.build(Thread.currentThread().getContextClassLoader().getResourceAsStream(CONFIG_FILE_NAME));
	    		Element root = doc.getRootElement();    		
	    		configroot = (Element)XPath.selectSingleNode(root, "//CsvConfig");
	    		
	    	}catch(Exception e){e.printStackTrace();}
    	}
    }
    
    public void writerExcel(List rs) throws Exception{
    	writerExcel(rs, null , null);
    }
    
    public void writerExcel(List rs, String configNode) throws Exception{
    	writerExcel(rs, configNode, null);
    }
    
	public void writerExcel(List rs, String configNode, String[] outitems) throws Exception{
		if(configNode!=null && !configNode.equals("")){
			this.configNode = configNode;
			if(CONFIG_FILE_NAME.equals(""))
				throw new RuntimeException("config file is not defined! Specify config file name first!"); 
			writeHeader(outitems);
			writeContentByConfig(rs, outitems);
		}
		else{
			//writeContent();
		}
    	writer.flush();
    	writer.close();
    }
    
    
	private void writeContentByConfig(List rs, String[] outitems) {
    	try {
			Element efields = (Element)XPath.selectSingleNode(configroot, "//" + this.configNode + "/Field");
			if(efields==null) throw new RuntimeException(this.configNode + "'s <Label> node is null!");
			String[] fields = efields.getText().split(",");
			
			//outitems setting
			if(outitems != null){
				fields = outitems;
			}
			
			for(Object item: rs){
				PropertyDescriptor[] props = Introspector.getBeanInfo(item.getClass()).getPropertyDescriptors();
				for(int i=0; i< fields.length; i++){
					String field = fields[i];
					for(PropertyDescriptor prop:props){
						if(prop.getName().equals(field)){
							String fieldValue = "";
							Object obj = prop.getReadMethod().invoke(item, null);
							if(i < fields.length-1){
								fieldValue= obj == null?"" + TAB: obj.toString()+TAB;
							}
							else
								fieldValue=obj == null?"" : obj.toString();
							writer.write(fieldValue.getBytes());
						}
					}
				}
				writer.write("\n".getBytes());
			}
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException(e);
		}
    	
	}
	private void writeHeader(String[] outitems){
    	try {
    		Element header = (Element)XPath.selectSingleNode(configroot, "//" + this.configNode + "/Label");
			if(header==null) throw new RuntimeException(this.configNode + "'s <Label> node is null!");
    		if(outitems == null){
    			writer.write(header.getText().replace(',', TAB).getBytes());
    		}else{
    			Element efields = (Element)XPath.selectSingleNode(configroot, "//" + this.configNode + "/Field");
    			if(efields==null) throw new RuntimeException(this.configNode + "'s <Label> node is null!");

    			String[] labels = header.getText().split(",");
    			String[] fields = efields.getText().split(",");
    			for(int j=0 ; j<outitems.length; j++){
    				String outitem = outitems[j];
    				for(int i=0; i< fields.length; i++){
    					String field = fields[i];
    					if(field.equals(outitem)){
    						if(j < outitems.length - 1)
    							writer.write((labels[i] + TAB).getBytes());
    						else
    							writer.write(labels[i].getBytes());
    						break;
    					}
    				}
    			}
    		}
    		
    		writer.write("\n".getBytes());
    			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException(e);
		}
    	
    }
    
    
    
    
    
    
    
    
    private String formatString(String tmp){
        if (tmp.indexOf('\n') != -1)
        {
            tmp = tmp.replace('\n', (char)(127));
        }
        
        if (tmp.indexOf(COMMA) != -1)
        {
            tmp = tmp.replaceAll(String.valueOf(COMMA), "，");
        }
        if (tmp.indexOf('\r') != -1)
        {
            tmp = tmp.replace('\r', (char)(127));
        }
        if (tmp.indexOf('\t') != -1)
        {
            tmp = tmp.replace('\t', (char)(127));
        }
        return tmp;
    }
}
